
//
//  CRSA.m
//  Ebochuanbu
//
//  Created by Ebo on 15/12/14.
//  Copyright © 2015年 chuanbu. All rights reserved.
//

#import "EBOrsa.h"
#import <Base64nl/Base64.h>

#define DocumentsDir [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]

#define OpenSSLRSAPublicKeyFile [DocumentsDir stringByAppendingPathComponent:@"rsa_public_key.pem"]

#define OpenSSLRSAPrivateKeyFile [DocumentsDir stringByAppendingPathComponent:@"rsa_private_key.pem"]

#define BUFFSIZE  1024

#define PADDING 1

NSString * const EBOPublicKey = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8z/h2o9j/TntAw8DQOHw+uiH0gNwqVBd7LGt23zdV9gxl9UXwe9HOyLBnUDiiLsjUXL2MPsEbLk/qSkzGXNJo4Rqib/piajaNh9NrWQCACi3RYtaczCJtYrxbwOWNAZe/Oop3roA/i7eEhyVWKGA1ARtsFgd8uG+7nuudpjM0wQIDAQAB";

NSString  * const EBOPrivateKey = @"MIICXAIBAAKBgQC8z/h2o9j/TntAw8DQOHw+uiH0gNwqVBd7LGt23zdV9gxl9UXwe9HOyLBnUDiiLsjUXL2MPsEbLk/qSkzGXNJo4Rqib/piajaNh9NrWQCACi3RYtaczCJtYrxbwOWNAZe/Oop3roA/i7eEhyVWKGA1ARtsFgd8uG+7nuudpjM0wQIDAQABAoGATTX+tQVrx3ugi2uBfaSbqksTd5j6b5TTxVr01zeQuWZUy5zxbNY1hgormRQFFM1s8uq52JARB7x4kaawnq12nRiWK1z5N067A0raS60nnm7OP9qrZUnpnzOoGHFi1mdaoE82wx/k2vuil9JSdjP/8KhAD/VSmTLJG5LCtOfA9sECQQDtkdb1nwjrIP2r1mKMx804fZWORb2Rp8D9z1a5JSpN7wbTRvqt0eraVrB/VtsOzpZt9IAk4VqOqH/QPUaQxF/XAkEAy3XOMvBS2Tw1yHLO9GLFQDhsWNBzu/EIu6q55bbV17fuQqsWsSFP80YMiGVmtgOXKRO9H28M3ho9OOsYeVTdJwJAUUwWDom0yJnKlTJRGTIKhWlcc4pkG+MXRQPd/o+8UV0ZrdVdVXw/bSY7UehMIF4L1mbUL0q67ZS14HIHouTAkwJAXw3Iqe+xJSCGGAHbQj2q3df+dnfcuh9f7x1SAEotGb0qqSb5UQO5MHS3gjmthLektWItZzQglNs5YxAivPyy3QJBANBiGm0Zi/f0CZ7uzQcuchvovH/EE0F5DrlRFJ77sW9w8kQK655/C4OXllfZFSO1Xf2fVeabxmwTYSuIO94UfyE=";

@implementation EBOrsa

+ (id)shareInstance
{
    static EBOrsa *_crsa = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _crsa = [[self alloc] init];
    });
    return _crsa;
}


- (instancetype)init
{
    self = [super init];
    if (self) {
        
        [self importRSAPrivateKey:EBOPrivateKey];
        [self importRSAPublicKey:EBOPublicKey];
    }
    return self;
}


- (void)importRSAPrivateKey:(NSString *)privateKey
{
    //格式化私钥
    const char *pstr = [privateKey UTF8String];
    int len = (int)[privateKey length];
    NSMutableString *result = [NSMutableString string];
    [result appendString:@"-----BEGIN RSA PRIVATE KEY-----\n"];
    int index = 0;
    int count = 0;
    while (index < len) {
        char ch = pstr[index];
        if (ch == '\r' || ch == '\n') {
            ++index;
            continue;
        }
        [result appendFormat:@"%c", ch];
        if (++count == 64)
        {
            [result appendString:@"\n"];
            count = 0;
        }
        index++;
    }
    [result appendString:@"\n-----END RSA PRIVATE KEY-----"];
    [result writeToFile:OpenSSLRSAPrivateKeyFile
             atomically:YES
               encoding:NSASCIIStringEncoding
                  error:NULL];
    
    
}

- (void)importRSAPublicKey:(NSString *)publicKey
{
    //格式化公钥
    NSMutableString *result = [NSMutableString string];
    [result appendString:@"-----BEGIN PUBLIC KEY-----\n"];
    int count = 0;
    for (int i = 0; i < [publicKey length]; ++i) {
        
        unichar c = [publicKey characterAtIndex:i];
        if (c == '\n' || c == '\r') {
            continue;
        }
        [result appendFormat:@"%c", c];
        if (++count == 64) {
            [result appendString:@"\n"];
            count = 0;
        }
    }
    [result appendString:@"\n-----END PUBLIC KEY-----"];
    [result writeToFile:OpenSSLRSAPublicKeyFile
             atomically:YES
               encoding:NSASCIIStringEncoding
                  error:NULL];
    
}

- (BOOL)importRSAKeyWithType:(EBOKeyType)type
{
    FILE *file;
    NSString *keyName = type == EBOKeyTypePublic ? @"rsa_public_key" : @"rsa_private_key";
    NSString *keyPath = [[NSBundle mainBundle] pathForResource:keyName ofType:@"pem"];
    NSString *str = @"";
    
    if (type == EBOKeyTypePublic) {
        str = OpenSSLRSAPublicKeyFile;
        
        file = fopen([str UTF8String], "rb");
    }else
    {
        str = OpenSSLRSAPrivateKeyFile;
        
        file = fopen([str UTF8String], "rb");

    }
    
    if (NULL != file)
    {
        if (type == EBOKeyTypePublic)
        {
            
            
            _rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL);
            assert(_rsa != NULL);
        }
        else
        {
            
            _rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);
            
            assert(_rsa != NULL);
        }
        
        fclose(file);
        
        return (_rsa != NULL) ? YES : NO;
    }
    
    return NO;
}




- (NSString *)encryptByRsa:(NSString*)content withKeyType:(EBOKeyType)keyType
{
 
    int status;
    if (![content isKindOfClass:[NSString class]]) {
        
        content = [NSString stringWithFormat:@"%@",content];
    }
    
    if (![self importRSAKeyWithType:keyType]){
        
        return nil;
    }
    
    NSData *plainData = [content dataUsingEncoding:NSUTF8StringEncoding];
    if (![plainData length])
    {
        return nil;
    }
    
    int len = (int)[plainData length];
    unsigned char *plainBuffer = (unsigned char *)[plainData bytes];
    
    //result len
    int clen = RSA_size(_rsa);
    unsigned char *cipherBuffer = calloc(clen, sizeof(unsigned char));
    
    
    switch (keyType) {
        case EBOKeyTypePublic:
            status = RSA_public_encrypt(len,plainBuffer,cipherBuffer, _rsa,PADDING);
            
            break;

        default:
            status = RSA_private_encrypt(len, plainBuffer, cipherBuffer,_rsa, PADDING);
            break;
    }
    
    
        if (status)
        {
            NSData *cipherData = [[NSData alloc] initWithBytes:cipherBuffer length:clen];
            
            free(cipherBuffer);
            
            NSString *cipherString = [cipherData base64EncodedString];
            
            
            return cipherString;
        }
   
        return nil;

    return nil;
}

- (NSString *) decryptByRsa:(NSString*)content withKeyType:(EBOKeyType)keyType
{
    if (![self importRSAKeyWithType:keyType])
        return nil;
    
    NSData *plainData = [content base64DecodedData];
    int status;
    
    int len = (int)[plainData length];
    unsigned char *cipherBuffer = (unsigned char *)[plainData bytes];
    
    //result len
    int mlen = RSA_size(_rsa);
    unsigned char *plainBuffer = calloc(mlen, sizeof(unsigned char));
    
    //RSA_private_decrypt(len, cipherBuffer, plainBuffer, _rsa, PADDING);

    switch (keyType) {
        case EBOKeyTypePublic:
            status = RSA_public_decrypt(len, cipherBuffer,plainBuffer, _rsa, PADDING);
            break;
            
        default:
            status = RSA_private_decrypt(len, cipherBuffer, plainBuffer, _rsa, PADDING);
            break;
    }
    
 
    
    if (status)
    {
        NSData *plainData = [[NSData alloc] initWithBytes:plainBuffer length:mlen];
        NSString *plainText =[[NSString alloc]initWithData:plainData encoding:NSUTF8StringEncoding];
        free(plainBuffer);
        
        return plainText;
    }
    

    
    return nil;
}



@end
